%include {
/*
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * SPDX-License-Identifier: GPL-3.0+
 * License-Filename: LICENSE
 */

#include "config.h"

#include <stdio.h>

#include "splay-tree.h"
#include "main.h"
#include "dp.h"

/* utf8 code at start if 1 */
static int utfseen = 0;

/* graph is strict if 1 */
static int isstrict = 0;
}


%syntax_error {
  printf("yyerror: %s\n","syntax error");
}

%token_type {int}
%start_symbol {startdot}

%token TOKEN_BRACEOPEN.
%token TOKEN_BRACECLOSE.
%token TOKEN_COMMA.
%token TOKEN_PLUS.
%token TOKEN_COLON.
%token TOKEN_BRACKETOPEN.
%token TOKEN_BRACKETCLOSE.
%token TOKEN_IS.
%token TOKEN_SC.
%token TOKEN_EOP.
%token TOKEN_STRICT.
%token TOKEN_DIGRAPH.
%token TOKEN_GRAPH.
%token TOKEN_UTF8BOM.
%token TOKEN_TEXT.
%token TOKEN_QTEXT.
%token TOKEN_NUM.
%token TOKEN_SC.
%token TOKEN_NODE.
%token TOKEN_EDGE.


%type text {char *}
%type ctext {char *}
%type thename {char *}
%type thetype {char *}
%type nidid {char *}
%type nid {struct dpepoint *}
%type sstatement {struct dpepoint *}

%left TOKEN_SUBGRAPH.
%left TOKEN_BRACEOPEN.

startdot2::= TOKEN_BRACEOPEN statements TOKEN_BRACECLOSE. { dp_eg (); }

utf::= TOKEN_UTF8BOM. { utfseen = 1; }
utf::= /* empty */. { utfseen = 0; }

startdot::= utf thetype(TT) thename(TN) startdot2. { dp_sg (TT,TN); } 
startdot::= /* empty */. { dp_eg (); }






thetype::= TOKEN_STRICT TOKEN_GRAPH. { isstrict = 1; $$ = "--"; }
thetype::= TOKEN_GRAPH. { isstrict = 0; $$ = "--"; }
thetype::= TOKEN_STRICT TOKEN_DIGRAPH. { isstrict = 1; $$ = "->"; }
thetype::= TOKEN_DIGRAPH. { isstrict = 0; $$ = "->"; }


thename(TN)::= text(TT). { TN = TT; }
thename(TN)::= /* empty */. { TN = NULL; }


/* example: "string" or "s"+"t"+"r"+"ing" */
ctext(CT)::= TOKEN_QTEXT(CL). { CT = CL; }
ctext(CT)::= ctext(CL) TOKEN_PLUS TOKEN_QTEXT(CR). { CT = dp_ccat (CL,CR); }


text(TX)::= TOKEN_TEXT(TT). { TX = TT; }
text(TX)::= TOKEN_NUM(NT). { TX = NT; }
text(TX)::= ctext(CT). { TX = CT; }


statements::= statement.
statements::= statements statement.

/* the semicolon after statement is optional, parse error if support routines have set a message */
statement::= statement2. { if (dp_chkerr()) { YYABORT; } }
statement::= statement2 TOKEN_SC.  { if (dp_chkerr()) { YYABORT; } }


statement2::= nstatement.
statement2::= estatement.
statement2::= astatement.
statement2::= sstatement.


nstatement::= nstatement_nidid oattrib. { dp_atype_graph (); }

nstatement_nidid::= nidid(ID). { dp_mknode0(ID); dp_atype_node(); }

/*
 * only for node definition and port+compass is ignored
 * nodeid
 * nodeid:port
 * nodeid:compass
 * nodeid:port:compass (port as in record/html label)
 */
nidid(NIDA)::= text(TX). { NIDA=TX; }
nidid(NIDA)::= text(TX) TOKEN_COLON text(TY). { NIDA=TX; /* ignore TY */ }
nidid(NIDA)::= text(TX) TOKEN_COLON text(TY) TOKEN_COLON text(TZ). { NIDA=TX; /* ignore TY TZ */ }


/*
 * nodeid
 * nodeid:port
 * nodeid:compass
 * nodeid:port:compass (port as in record/html label)
 */
nid(RES)::= text(TX) TOKEN_COLON text(TY) TOKEN_COLON text(TZ). { RES = dp_mknid (TX,TY,TZ); }
nid(RES)::= text(TX) TOKEN_COLON text(TY). { RES = dp_mknid (TX,TY,NULL); }
nid(RES)::= text(TX). { RES = dp_mknid (TX,NULL,NULL); }

sattr::= text(LA) TOKEN_IS text(LR). { dp_aset (LA,LR); }

sattr2::= sattr.
sattr2::= text(TX). { dp_aset (TX,"true"); }


iattr::= sattr2 iattr.
iattr::= sattr2 TOKEN_COMMA iattr.
iattr::= /* empty */.

tattr::= TOKEN_BRACKETOPEN iattr TOKEN_BRACKETCLOSE.

oattrib::= tattr oattrib.
oattrib::= /* empty */.

estatement::= estatement_nid  estatement_erhs oattrib. { dp_ende (); dp_clrep(); }
estatement::= estatement_sstatement estatement_erhs oattrib. { dp_ende (); dp_clrep(); }


estatement_nid ::= nid(NI). { dp_starte1 (NI); }

estatement_erhs ::= . { dp_newe (); }

estatement_sstatement::= sstatement(NI). { dp_starte2 (NI); }


erhs::= TOKEN_EOP(EO) erhs_nid.  { dp_cke (EO); }
erhs::= TOKEN_EOP(EO) erhs_nid erhs.  { dp_cke (EO); }
erhs::= TOKEN_EOP(EO) erhs_sstatement. { dp_cke (EO); }
erhs::= TOKEN_EOP(EO) erhs_sstatement erhs. { dp_cke (EO); }


erhs_nid::= nid(NI). { dp_ine (NI); }

erhs_sstatement::= sstatement(NI). { dp_ine (NI); }

astatement::= atype tattr. { dp_atype_graph (); }
astatement::= aset. { dp_atype_graph (); }


atype::= TOKEN_GRAPH. { dp_atype_graphdef (); }
atype::= TOKEN_NODE. { dp_atype_nodedef (); }
atype::= TOKEN_EDGE. { dp_atype_edgedef (); }


aset::= text(LS) TOKEN_IS text(RS). { dp_aset (LS,RS); }


sstatement(RES)::= shead TOKEN_BRACEOPEN statements TOKEN_BRACECLOSE. { RES = dp_endss (); }

sstatement_a::= .{ dp_namedsubg (NULL); }

sstatement(RES)::= TOKEN_BRACEOPEN sstatement_a statements TOKEN_BRACECLOSE. { RES = dp_endss (); }


shead::= TOKEN_SUBGRAPH text(SN). { dp_namedsubg (SN); }




/* end. */
